大整数-减法


问题描述

本文主要给出大数减法的一般思路。关于大数的一般性阐述可以参看大整数-加法-demo这篇博客。

思路

基本来说,还是大整数的那套思路。
要进行处理的数字,超过了计算机语言所能提供类型的最大范围。只能自己写数组存储每一位数字。由于不是内置类型,所以没有相应操作的支持。只能自己写,人工模拟减法操作。

  • 加法主要是:从低位到高位,逐位相加,超过10的部分要”进位”
  • 减法主要是:从低位到高位,逐位相减,不够减的部分要”借位”

当然,具体写的时候,减法和加法还是有一些区别。下面这些点需要注意:

  1. 首先,减法需要判断大小。只能是大数 - 小数的时候才能用上面的规则,也就是说对于 2 - 8这种类型应该先计算 8 - 2 = 6, 然后再加上负号,得到-6。
  2. 其次,输出的时候存在前导0的情形。用string实现,加法不存在前导0的情形,直接依次输出就行。减法输出的时候,不行。可能存在前导0的原因是因为,减法如果不减到最高位,你是不知道之前的这些0是前导0还是中间的0.只要最高位计算完毕之后你才知道。
  3. 我在写的时候由于是用string类型来存储大整数,所以在比较两个数大小的时候相对简单一点。如果数位相同的时候可以直接比较。但是,我之前忽略了一点就是,当数位不相同的时候,这种情形也是需要考虑的。比如66 - 8。如果直接用字符串比较,肯定会得到错误的结果。

代码

/* 
input:
多组输入数据; 字符串组织;

process:
    1.读入a,b;
    2.判断:如果 a < b, 交换a与b的值
    3.计算a_sz, c = 0;
    3.循环:i < a_sz
        3.1.先累加:left = a[i] + c;
        3.2.判断:i < b_sz
            3.2.1.true, right = b[i]
            3.2.2.false, right = 0;
        3.3.判断:left >= right
            3.3.1.true,够减,计算当前位 left - right; c = 0;
            3.3.2.flase, 不够减,计算当前位 left + 10 - right; c = - 1;
    4.返回ret
output:

测试数据:
66 9
1 2
88 5
2 999999999999
456786798787 4564564857921456645789789
*/

#include <iostream>
#include <string>
#include <fstream>
#define LOCAL

std::string bign_minus( const std::string& a, const std::string& b );

int main( void )
{
#ifdef LOCAL
    std::ifstream cin;
    cin.open( "input.dat" );
#endif
    std::string a, b;
    while( cin >> a >> b )
    {
        bool flag = true;
        if( a.size() < b.size() || (a.size() == b.size() && a < b) )
        { std::string tmp = a; a = b; b = tmp; flag = false; }

        std::string ret = bign_minus( std::string(a.rbegin(), a.rend()), std::string(b.rbegin(), b.rend()) );
        int sz = ret.size();
        int i = 0;
        for( i = sz - 1; ret[i] == '0'; --i );
        if(!flag)
            std::cout << '-';
        for( int j = i; j >= 0; --j )
            std::cout << ret[j];
        std::cout << std::endl;
    }
#ifdef LOCAL
    cin.close();
#endif
    return 0;
}

std::string bign_minus( const std::string& a, const std::string& b )
{
    std::string ret;
    int a_sz = a.size();
    int b_sz = b.size();
    int c = 0;

    for( int i = 0; i < a_sz; ++i )
    {
        int left = c + a[i] - '0';
        int right = (i < b_sz)?(b[i] - '0'):0;

        if( left >= right )
        {  
            ret.push_back( '0' + left - right );
            c = 0;
        }
        else
        {
            ret.push_back( '0' + 10 + left - right );
            c = -1;
        }
    }
    return ret;
}

注意

  • 减法的特性:借位
  • 注意上述算法只能是”大-小”,如果遇见”小-大”的情形,先需要交换,然后进行计算,最后再添加负号。负号容易忘了
  • 输出的前导0要处理

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言中可以使用结构体来实现大整数减法,具体实现方式如下: ``` #include <stdio.h> #include <string.h> #define MAX_LEN 1000 // 定义最大长度 typedef struct { int len; // 数字串长度 char num[MAX_LEN + 1]; // 数字串 } BigInteger; void subtract(BigInteger* a, BigInteger* b, BigInteger* result) { int i, carry = 0; for (i = 0; i < b->len; i++) { int temp = a->num[i] - b->num[i] - carry; if (temp < 0) { temp += 10; carry = 1; } else { carry = 0; } result->num[i] = temp + '0'; } for (; i < a->len; i++) { int temp = a->num[i] - '0' - carry; if (temp < 0) { temp += 10; carry = 1; } else { carry = 0; } result->num[i] = temp + '0'; } for (i = a->len - 1; i >= 0; i--) { if (result->num[i] != '0') { break; } } result->len = i + 1; } int main() { BigInteger a, b, result; // 初始化数字串 scanf("%s", a.num); scanf("%s", b.num); a.len = strlen(a.num); b.len = strlen(b.num); // 执行减法操作 subtract(&a, &b, &result); // 输出结果 for (int i = result.len - 1; i >= 0; i--) { printf("%c", result.num[i]); } printf("\n"); return 0; } ``` 上述代码中,我们定义了一个结构体 `BigInteger`,用于存储大整数。其中,`len` 表示数字串长度,`num` 表示数字串本身。函数 `subtract` 实现了大整数减法。 在 `main` 函数中,我们首先读入两个数字串,然后调用 `subtract` 函数进行减法操作,最后输出结果。 注意,这里假设输入的数字串均为非负整数,若需要处理负数,则可以先判断两个数字串的正负性,再分情况讨论进行减法操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值